package com.smart.wap.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.ObjUtil;
import com.alibaba.fastjson2.JSONObject;
import com.alicp.jetcache.Cache;
import com.smart.common.cache.CacheService;
import com.smart.manager.member.entities.enums.ChickenState;
import com.smart.manager.member.entities.models.MemberMaterialChicken;
import com.smart.manager.member.entities.models.MemberProfileAccount;
import com.smart.manager.member.entities.models.query.QMemberMaterialChicken;
import com.smart.manager.member.entities.models.query.QMemberMaterialPig;
import com.smart.manager.member.entities.models.query.QMemberProfileAccount;
import com.smart.manager.member.entities.views.MemberView;
import com.smart.manager.member.entities.views.query.QMemberView;
import com.smart.manager.system.repository.ConfigRepository;
import com.smart.service.remind.RemindService;
import com.smart.utils.MemberAcl;
import com.smart.wap.assembler.ChickenCaches;
import com.smart.wap.bodys.ChickenBody;
import io.ebean.DB;
import io.ebean.SqlRow;
import io.ebean.annotation.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 猪仔操作
 *
 * @author leo
 * @date 2023/09/21
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class ChickenService {
    private final CacheService cacheService;
    private final ConfigRepository configRepository;

    private final RemindService remindService;


    /**
     * 获取鸡
     *
     * @return {@link Integer}
     */
    public Integer getChicken(ChickenBody.QueryBody body) {
        Long loginId = MemberAcl.getLoginId();
        if (ObjUtil.isNotNull(body.getId())) {
            loginId = body.getId();
        }
        String sql = "SELECT sum(pig.chicken) as chicken FROM member_material_pig AS pig WHERE pig.chicken IS NOT NULL  AND pig.member = " + loginId;
        SqlRow row = DB.sqlQuery(sql).findOne();
        if (ObjUtil.isNotNull(row)) {
            return row.getInteger("chicken");
        }
        return 0;
    }


    /**
     * 获取能偷的蛋
     *
     * @param body
     * @return {@link List}<{@link MemberMaterialChicken}>
     */
    public List<MemberMaterialChicken> getEgg(ChickenBody.QueryBody body) {
        Long loginId = MemberAcl.getLoginId();
        Opt<Long> opt = Opt.ofNullable(body.getId());
        if (opt.isPresent()) {
            loginId = body.getId();
        }
        String sql = String.format(" t0.display_time <= '%s' AND t0.state = 'L1' AND t0.member = %s ", LocalDateTime.now().format(DatePattern.createFormatter(DatePattern.NORM_DATETIME_PATTERN)), loginId);
        return new QMemberMaterialChicken().raw(sql).findList();
    }


    /**
     * 获取已经收取的蛋
     *
     * @param body
     * @return {@link List}<{@link MemberMaterialChicken}>
     */
    public List<MemberMaterialChicken> getEggOne(ChickenBody.QueryBody body) {
        Long loginId = MemberAcl.getLoginId();
        Opt<Long> opt = Opt.ofNullable(body.getId());
        if (opt.isPresent()) {
            loginId = body.getId();
        }
        return new QMemberMaterialChicken().or().member.id.eq(loginId).receive.id.eq(loginId).endOr().state.in(ChickenState.L3, ChickenState.L2, ChickenState.L4).pickUpTime.desc().findList();
    }

    /**
     * 收取蛋
     */
    @Transactional(rollbackFor = Exception.class)
    public Integer addEgg(ChickenBody.QueryBody1 body) {
        LocalDateTime time = LocalDateTime.now();
        Long loginId = MemberAcl.getLoginId();
        log.warn("开始收取蛋 {}", body);
        int a = 0;
        MemberProfileAccount account = new QMemberProfileAccount().member.id.eq(loginId).setMaxRows(1).findOne();

        if (ObjUtil.isNull(body.getId())||ObjUtil.isNull(body)) {
            //收蛋逻辑
            String sql = String.format(" t0.display_time <= '%s' AND t0.state = 'L1' AND t0.member = %s", time.format(DatePattern.createFormatter(DatePattern.NORM_DATETIME_PATTERN)), loginId);
            List<MemberMaterialChicken> chickens = new QMemberMaterialChicken().raw(sql).findList();
            chickens.forEach(x -> {
                x.setState(ChickenState.L3).setPickUpTime(time).setReceive(x.getMember());
            });
            a = chickens.size();
            DB.updateAll(chickens);
            account.setEggQuantity(account.getEggQuantity() + chickens.size()).update();
        } else {
            Cache<Long, List<Long>> limitCache = cacheService.getLimitCache();
            List<Long> longs1 = limitCache.get(loginId);
            if (ObjUtil.isNull(longs1)){
                longs1 = new ArrayList<>();
            }

            int winningPercentage = 50; // 设定偷取概率为50%
            List<Boolean> attributeList = new QMemberMaterialPig().member.id.eq(loginId).isFull.eq(true).select(QMemberMaterialPig.Alias.isFull).findSingleAttributeList();
            JSONObject probability = configRepository.readCache("Probability");
            if (ObjUtil.isNull(attributeList)){
                //没有猪的为普通用户
                winningPercentage = probability.getInteger("default");
            }else {
                //判断如果为true的则为高级用户
                long count = attributeList.stream().filter(x -> x).count();
                if (count>0){
                    winningPercentage = probability.getInteger("senior");
                }else {
                    winningPercentage = probability.getInteger("centre");
                }
            }

            log.warn("几率 = {}",winningPercentage);
            MemberMaterialChicken chicken = new QMemberMaterialChicken().id.eq(body.getId()).state.eq(ChickenState.L1).findOne();

            Assert.isFalse(ObjUtil.isNull(chicken), "收取的蛋不存在,或者已被收取");
            Assert.isFalse(longs1.contains(chicken.getMember().getId()), "今日已经偷了该用户!");
            //不管成功还是失败都需要扣除
            Assert.isFalse(ObjUtil.isNull(account), "账户信息不存在");
            Integer quantity = account.getChickenQuantity();
            Assert.isTrue(quantity >= 1, "今日偷蛋次数不足!");
            //偷蛋逻辑
            Random random = new Random();
            int randomNumber = random.nextInt(100);
            if (randomNumber < winningPercentage) {
                List<Long> longs = new ArrayList<>();
                if (ObjUtil.isNotNull(chicken.getFailMember())) {
                    longs = chicken.getFailMember();
                }
                longs.add(loginId);
                Assert.isFalse(false, "偷蛋失败!");
            }
            a = 1;
            //鸡蛋加一
            account.setEggQuantity(account.getEggQuantity() + 1);
            //保存
            account.setChickenQuantity(quantity - 1).update();
            //没有抛出异常 偷蛋成功
            MemberView view = new QMemberView().id.eq(loginId).findOne();
            chicken.setReceive(view).setState(ChickenState.L2).setPickUpTime(time).update();
            longs1.add(chicken.getMember().getId());
            //发生被偷提醒
            remindService.sendStealing(chicken.getMember().getId(),chicken);
            //删除缓存
            cacheService.getChickenStealCache().remove(chicken.getMember().getId());
            cacheService.getLimitCache().put(loginId, longs1);
        }
        return a;
    }


    /**
     * 有蛋用户  TODO: 弃用
     * @return {@link List}<{@link ChickenCaches.ChickenInfo}>
     */
    public List<ChickenCaches.ChickenInfo> getInfoList() {
        Cache<String, List<ChickenCaches.ChickenInfo>> infoCache = cacheService.getChickenInfoCache();
        List<ChickenCaches.ChickenInfo> chickenCaches = infoCache.get("MemberIds");
        if (ObjUtil.isNull(chickenCaches)) {
            String sql = String.format(" t0.display_time <= '%s' AND t0.state = 'L1'", LocalDateTime.now().format(DatePattern.createFormatter(DatePattern.NORM_DATETIME_PATTERN)));
            List<MemberMaterialChicken> list = new QMemberMaterialChicken().raw(sql).findList();
            Set<MemberView> collect = list.stream().map(MemberMaterialChicken::getMember).collect(Collectors.toSet());
            chickenCaches = BeanUtil.copyToList(collect, ChickenCaches.ChickenInfo.class);
            infoCache.put("MemberIds", chickenCaches);
        }
        return chickenCaches;
    }


    /**
     * 固定20人
     * @return {@link List}<{@link ChickenCaches.ChickenInfo}>
     */
    public List<ChickenCaches.ChickenInfo> getInfoOneList() {
        String loginId = MemberAcl.getLoginId().toString();
        Cache<String, List<ChickenCaches.ChickenInfo>> infoCache = cacheService.getChickenInfoCache();
        List<ChickenCaches.ChickenInfo> chickenCaches = infoCache.get(loginId);
        if (ObjUtil.isNull(chickenCaches)) {
            List<MemberMaterialChicken> list = new QMemberMaterialChicken().orderBy("RANDOM()").setMaxRows(20).findList();
            Set<MemberView> collect = list.stream().map(MemberMaterialChicken::getMember).collect(Collectors.toSet());
            chickenCaches = BeanUtil.copyToList(collect, ChickenCaches.ChickenInfo.class);
            infoCache.put(loginId, chickenCaches);
        }
        return chickenCaches;
    }



    /**
     * 获取偷取列表
     */
    public List<ChickenCaches.ChickenSteal> getSteal() {
        Long loginId = MemberAcl.getLoginId();
        Cache<Long, List<ChickenCaches.ChickenSteal>> stealCache = cacheService.getChickenStealCache();
        List<ChickenCaches.ChickenSteal> steals = stealCache.get(loginId);
        if (ObjUtil.isNull(steals)) {
            List<MemberMaterialChicken> chickens = new QMemberMaterialChicken().state.in(ChickenState.L2).receive.id.eq(loginId).pickUpTime.desc().findList();
            steals = BeanUtil.copyToList(chickens, ChickenCaches.ChickenSteal.class);
            stealCache.put(loginId, steals);
        }
        return steals;
    }

    /**
     * 获取偷取列表
     */
    public List<ChickenCaches.ChickenSteal> getStolen() {
        Long loginId = MemberAcl.getLoginId();
        List<MemberMaterialChicken> chickens = new QMemberMaterialChicken().state.in(ChickenState.L2).member.id.eq(loginId).pickUpTime.desc().findList();
        return BeanUtil.copyToList(chickens, ChickenCaches.ChickenSteal.class);
    }

    /**
     * 获取收取记录
     */
    public List<ChickenCaches.ChickenSteal> getCharge() {
        Long loginId = MemberAcl.getLoginId();
        List<MemberMaterialChicken> chickens = new QMemberMaterialChicken().state.in(ChickenState.L3).member.id.eq(loginId).pickUpTime.desc().findList();
        return BeanUtil.copyToList(chickens, ChickenCaches.ChickenSteal.class);
    }

    /**
     * 7天排行榜
     */
    public List<ChickenCaches.ChickenRanking> getGeeRanking() {
//        Long loginId = MemberAcl.getLoginId();
        String sql = "SELECT t1.id,t1.nick_name AS name,t1.avatar, t0.receive, t0.count_receive AS egg FROM member_profile_main AS t1 JOIN (SELECT receive,COUNT ( receive ) AS count_receive FROM member_material_chicken WHERE state = 'L2' AND receive IS NOT NULL AND generation_time >= CURRENT_DATE - INTERVAL '7' DAY GROUP BY receive ) AS t0 ON t1.ID = t0.receive ORDER BY t0.count_receive DESC limit 10;";
        return DB.sqlQuery(sql).findList().stream().map(item -> BeanUtil.copyProperties(item, ChickenCaches.ChickenRanking.class)).collect(Collectors.toList());
    }


}
